package com.ghck.server.controller.exception;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.ghck.server.exception.ErrorConstant;
import com.ghck.server.exception.ErrorInfo;
import com.ghck.server.exception.GhckException;
import com.ghck.shop.exception.ShopServerException;

@ResponseStatus(value = HttpStatus.OK)
@ControllerAdvice(basePackages = "com.ghck.server.controller")
public class BasicExceptionHandler {
    private final static Logger logger = LoggerFactory.getLogger(BasicExceptionHandler.class);

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseBody
    public ErrorInfo handleIllegalArgument(IllegalArgumentException ex) {
        logger.error(ex.getMessage(), ex);
        return new ErrorInfo(ErrorConstant.PARAM_ERROR.getErrorCode(),ErrorConstant.PARAM_ERROR.getMsg());
    }

    @ExceptionHandler(value = {GhckException.class})
    @ResponseBody
    public ErrorInfo handleServerError(GhckException ex) {
        logger.error(ex.getMessage(), ex);
        String errorMessage = ex.getMessage();
        return new ErrorInfo(ErrorConstant.SERVER_ERROR.getErrorCode(), errorMessage);
    }
    
    @ExceptionHandler(value = {ShopServerException.class})
    @ResponseBody
    public ErrorInfo handleShopServerException(ShopServerException ex) {
        logger.error(ex.getMessage(), ex);
        String errorMessage = ex.getMessage();
        return new ErrorInfo(ErrorConstant.SERVER_ERROR.getErrorCode(), errorMessage);
    }
    
    private Class<? extends Authentication> anonymousClass = AnonymousAuthenticationToken.class;
    public boolean isAnonymous(Authentication authentication) {
        if ((anonymousClass == null) || (authentication == null)) {
            return false;
        }
        return anonymousClass.isAssignableFrom(authentication.getClass());
    }
    @ExceptionHandler(value = {AccessDeniedException.class})
    @ResponseBody
    public ErrorInfo handleAccessDeniedException(HttpServletRequest request,HttpServletResponse response,AccessDeniedException ex) {
    	String errorMessage = ex.getMessage();
    	Enumeration<String> headers = request.getHeaderNames();
    	StringBuffer sb = new StringBuffer();
    	while (headers.hasMoreElements()) {
			String key = (String) headers.nextElement();
			sb.append(key).append("=").append(request.getHeader(key)).append("\n");
		}
    	String path = request.getRequestURI().replaceFirst( request.getContextPath(), "");
    	if(isAnonymous(SecurityContextHolder.getContext().getAuthentication())){
    		logger.info("一个匿名用户访问一个受保护的资源系统拒绝:{},path={},请求头为:{}",ex.getMessage(),path,sb.toString());
    		//return new ErrorInfo(ErrorConstant.ACCOUNT_EXPIRED.getErrorCode(), errorMessage);
    		return new ErrorInfo(ErrorConstant.ACCOUNT_EXPIRED.getErrorCode(), "认证没有通过");
    	}else {
    		logger.info("一个未授权的请求被系统拦截:{},path={},请求头为:{}",ex.getMessage(),path,sb.toString());
            return new ErrorInfo(ErrorConstant.CERTIFICATION_AUTHORITY_FAILS.getErrorCode(), "没有权限");
    	}
        
    }

}




